package com.mobilesales.android.activities.tasks;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.Spinner;
import android.widget.TextView;

import com.mobilesales.android.R;
import com.mobilesales.android.activities.ModelActivity;
import com.mobilesales.android.adapters.SimpleClientAdapter;
import com.mobilesales.android.adapters.EmployeeAdapter;
import com.mobilesales.android.adapters.TaskStatusAdapter;
import com.mobilesales.android.adapters.TaskTypeAdapter;
import com.mobilesales.android.database.ClientManager;
import com.mobilesales.android.database.EmployeeManager;
import com.mobilesales.android.database.TaskManager;
import com.mobilesales.android.model.clients.Client;
import com.mobilesales.android.model.employees.Employee;
import com.mobilesales.android.model.exceptions.ServiceUnavailableException;
import com.mobilesales.android.model.tasks.CyclicTask;
import com.mobilesales.android.model.tasks.Schedule;
import com.mobilesales.android.model.tasks.Task;
import com.mobilesales.android.model.tasks.TaskStatus;
import com.mobilesales.android.model.tasks.TaskType;
import com.mobilesales.android.services.TaskServiceClient;
import com.mobilesales.android.util.Constants;
import com.mobilesales.android.util.DateUtil;
import com.mobilesales.android.util.LogFlags;
import com.mobilesales.android.util.MessageBox;
import com.mobilesales.android.util.SelectDateTime;
import com.mobilesales.android.util.Settings;

public class StoreTask extends ModelActivity<Task> {

	private int taskId;
	private boolean isCyclicTask;

	private TaskTypeAdapter taskTypeAdapter;
	private TaskStatusAdapter taskStatusAdapter;
	private SimpleClientAdapter clientAdapter;
	private EmployeeAdapter employeeAdapter;

	private Spinner taskTypeSelect;
	private Spinner taskStatusSelect;
	private Spinner clientSelect;
	private Spinner employeeSelect;
	private EditText startTimeField;
	private EditText endTimeField;
	private EditText dateField;
	private EditText infoField;
	private SeekBar intervalSeekBar;
	private EditText priorityField;
	private LinearLayout intervalRow;
	private TextView taskIntervalLbl;

	private Calendar cal;

	SelectDateTime datetime = null;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.task_store);

		taskTypeSelect = (Spinner) this.findViewById(R.id.taskTypeSpinner);
		taskStatusSelect = (Spinner) this.findViewById(R.id.taskStatusSpinner);
		clientSelect = (Spinner) this.findViewById(R.id.clientSpinner);
		employeeSelect = (Spinner) this.findViewById(R.id.employeeSpinner);
		infoField = (EditText) this.findViewById(R.id.infoTxt);
		startTimeField = (EditText) this.findViewById(R.id.startTime);
		endTimeField = (EditText) this.findViewById(R.id.endTime);
		dateField = (EditText) this.findViewById(R.id.date);
		intervalSeekBar = (SeekBar) this.findViewById(R.id.taskIntervalSeekBar);
		intervalRow = (LinearLayout) this.findViewById(R.id.taskIntervalRow);
		priorityField = (EditText) this.findViewById(R.id.priority);
		taskIntervalLbl = (TextView) this.findViewById(R.id.taskIntervalLbl);

		datetime = new SelectDateTime(this);

		cal = Calendar.getInstance();
		SimpleDateFormat dft = null;

		dft = new SimpleDateFormat("hh:mm a", Locale.getDefault());
		String strTime = dft.format(cal.getTime());
		startTimeField.setText(strTime);

		// endTimeField.setText(strTime);
		dft = new SimpleDateFormat("HH:mm", Locale.getDefault());
		startTimeField.setTag(dft.format(cal.getTime()));

		// endTimeField.setTag(dft.format(cal.getTime()));

		dateField.setInputType(0);

		intervalSeekBar
				.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {

					public void onStopTrackingTouch(SeekBar seekBar) {
					}

					public void onStartTrackingTouch(SeekBar seekBar) {
					}

					public void onProgressChanged(SeekBar seekBar,
							int progress, boolean fromUser) {
						taskIntervalLbl.setText(progress + " d");
					}
				});

		dateField.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				// TODO Auto-generated method stub
				// my_time_dialog_ngay_den();

				datetime.my_time_dialog_ngay_den(dateField);
			}
		});
		startTimeField.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				// TODO Auto-generated method stub

				datetime.showTimePickerDialog(startTimeField);
			}
		});

		endTimeField.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				// TODO Auto-generated method stub
				datetime.showTimePickerDialog(endTimeField);
			}
		});

		Bundle bundle = this.getIntent().getExtras();
		if (bundle != null && bundle.containsKey(Constants.IsCyclicTask)) {

			this.initializeSelectLists();
			isCyclicTask = bundle.getBoolean(Constants.IsCyclicTask);

			if (!isCyclicTask) {
				intervalRow.setVisibility(View.GONE);
				taskIntervalLbl.setVisibility(View.GONE);
			} else {
				intervalSeekBar.setProgress(1);
				taskIntervalLbl.setText("1 d");
			}

			Date now = new Date();
			SimpleDateFormat sim = new SimpleDateFormat("yyyy-mm-dd");

			if (bundle.containsKey(Constants.SelectedDate)) {
				Date date = (Date) bundle.get(Constants.SelectedDate);
				dateField.setText(sim.format(date));
			} else {
				dateField.setText(sim.format(now));
			}
			startTimeField.setText(DateUtil.toTimeString(now));
			endTimeField.setText(DateUtil.toTimeString(now));

			if (bundle.containsKey(Constants.TaskId)) {

				taskId = bundle.getInt(Constants.TaskId);
				loadItem();
			} else {
				((Button) this.findViewById(R.id.actionBtn))
						.setText(getString(R.string.Add));
			}

		} else {
			MessageBox.show(this, getString(R.string.ErrorTask));
			finish();
		}
	}

	private void initializeSelectLists() {
		List<TaskStatus> statuses = this.getTaskStatusList();
		List<TaskType> types = this.getTaskTypeList();
		List<Client> clients = this.getClients();
		List<Employee> employees = this.getEmployees();
		if (statuses != null && types != null && clients != null) {
			this.taskStatusAdapter = new TaskStatusAdapter(this,
					R.layout.select_list_item, statuses);
			taskStatusSelect.setAdapter(taskStatusAdapter);
			this.fixSpinner(taskStatusSelect);
			this.taskTypeAdapter = new TaskTypeAdapter(this,
					R.layout.select_list_item, types);
			taskTypeSelect.setAdapter(taskTypeAdapter);
			this.fixSpinner(taskTypeSelect);
			this.clientAdapter = new SimpleClientAdapter(this,
					R.layout.select_list_item, clients, true);
			clientSelect.setAdapter(clientAdapter);
			this.fixSpinner(clientSelect);
			this.employeeAdapter = new EmployeeAdapter(this,
					R.layout.select_list_item, employees);
			employeeSelect.setAdapter(employeeAdapter);
			this.fixSpinner(employeeSelect);
		} else {
			MessageBox.show(this, getString(R.string.ErrorSelectLists));
		}

	}

	private void loadItem() {
		Task task = null;
		if (isCyclicTask)
			task = getCyclicTask(taskId);
		else
			task = getTask(taskId);
		if (task != null)
			this.setModel(task);
		else {
			MessageBox.show(this, getString(R.string.ErrorTask));
			finish();
		}
	}

	@Override
	protected void setModel(Task model) {
		super.setModel(model);
		if (isCyclicTask) {
			this.intervalSeekBar.setProgress(((CyclicTask) model).TaskInterval);
			taskIntervalLbl.setText(String.valueOf(this.intervalSeekBar
					.getProgress()));
		}

		taskTypeSelect.setSelection(taskTypeAdapter
				.getPosition(model.TaskType.Id));
		taskStatusSelect.setSelection(taskStatusAdapter
				.getPosition(model.TaskStatus.Id));

		Integer employeeId;
		if (isCyclicTask)
			employeeId = ((CyclicTask) model).EmployeeId;
		else
			employeeId = getEmployeeIdFromSchedule(model.ScheduleId);
		if (employeeId != null) {
			employeeSelect
					.setSelection(employeeAdapter.getPosition(employeeId));
		} else {
			MessageBox.show(this, getString(R.string.ErrorEmployee));
			finish();
		}

		clientSelect.setSelection(clientAdapter.getPosition(model.ClientId));
		String startTime = model.StartTime.split(" ")[1];
		String endTime = model.EndTime.split(" ")[1];
		String date = model.EndTime.split(" ")[0];

		startTimeField.setText(startTime);
		endTimeField.setText(endTime);

		date = datetime.FormatDate(date);

		dateField.setText(date);
		infoField.setText(model.Info);
		priorityField.setText(String.valueOf(model.Priority));
	}

	public void store(View v) {
		if (validate()) {
			Task task = this.getModel();
			if (task == null) {
				if (isCyclicTask)
					task = new CyclicTask();
				else
					task = new Task();
			}

			int employeeId = ((Employee) this.employeeSelect.getSelectedItem()).Id;

			if (isCyclicTask) {
				((CyclicTask) task).TaskInterval = intervalSeekBar
						.getProgress();
				((CyclicTask) task).EmployeeId = employeeId;
				((CyclicTask) task).ScheduleId = null;
			}

			Client selectedClient = (Client) clientSelect.getSelectedItem();
			task.ClientId = (selectedClient.Id != 0) ? selectedClient.Id : null;

			task.StartTime = dateField.getText() + " "
					+ startTimeField.getText();
			task.EndTime = dateField.getText() + " " + endTimeField.getText();
			task.Info = infoField.getText().toString();
			task.Priority = Integer
					.parseInt(priorityField.getText().toString());
			task.TaskStatus = (TaskStatus) taskStatusSelect.getSelectedItem();
			task.TaskType = (TaskType) taskTypeSelect.getSelectedItem();

			if (isCyclicTask) {
				if (save((CyclicTask) task)) {
					setResult(RESULT_OK);
					finish();
				} else
					MessageBox.show(this, getString(R.string.ErrorSave));
			} else {
				if (save(task, employeeId))
					finish();
				else
					MessageBox.show(this, getString(R.string.ErrorSave));
			}

		} else {
			MessageBox.show(this, getString(R.string.ErrorValidate));
		}
	}

	private boolean save(CyclicTask task) {
		TaskServiceClient cli = new TaskServiceClient(Settings.TaskService());
		try {
			cli.storeCyclicTask(task);
			return true;
		} catch (ServiceUnavailableException e) {
			Log.e(LogFlags.RestService, e.getMessage(), e);
		}
		return false;
	}

	private boolean save(Task task, int employeeId) {
		TaskServiceClient cli = new TaskServiceClient(Settings.TaskService());
		try {
			cli.storeTask(task, employeeId);
			return true;
		} catch (ServiceUnavailableException e) {
			Log.e(LogFlags.RestService, e.getMessage(), e);
		}
		return false;
	}

	private Integer getEmployeeIdFromSchedule(Integer scheduleId) {
		TaskManager manager = new TaskManager(this);
		Schedule s = manager.GetSchedule(scheduleId);
		manager.Close();
		if (s.EmployeeId != 0)
			return s.EmployeeId;
		return null;
	}

	private List<Employee> getEmployees() {
		EmployeeManager manager = new EmployeeManager(this);
		List<Employee> employees = manager.GetEmployeeList();
		manager.Close();
		return employees;
	}

	private List<Client> getClients() {
		ClientManager manager = new ClientManager(this);
		List<Client> clients = manager.GetClientList();
		manager.Close();
		return clients;
	}

	private CyclicTask getCyclicTask(int taskId) {
		TaskManager manager = new TaskManager(this);
		CyclicTask tsk = manager.GetCyclicTask(taskId);
		manager.Close();
		return tsk;
	}

	private Task getTask(int taskId) {
		TaskManager manager = new TaskManager(this);
		Task tsk = manager.GetTask(taskId);
		manager.Close();
		return tsk;
	}

	private List<TaskType> getTaskTypeList() {
		TaskManager manager = new TaskManager(this);
		List<TaskType> types = manager.GetTaskTypeList();
		manager.Close();
		return types;
	}

	private List<TaskStatus> getTaskStatusList() {
		TaskManager manager = new TaskManager(this);
		List<TaskStatus> statuses = manager.GetTaskStatusList();
		manager.Close();
		return statuses;
	}

	@Override
	protected boolean validate() {
		boolean valid = true;
		String date = this.dateField.getText().toString();
		if (DateUtil.parseShortDate(date) == null) {
			this.dateField.setError(getString(R.string.ErrorInvalidValue));
			valid = false;
		}

		String timeRegexp = "(20|21|22|23|[01]\\d|\\d)(([:][0-5]\\d){1,2})";

		String startTime = this.startTimeField.getText().toString();
		if (!startTime.matches(timeRegexp)) {
			this.startTimeField.setError(getString(R.string.ErrorInvalidValue));
			valid = false;
		}

		String endTime = this.endTimeField.getText().toString();
		if (!endTime.matches(timeRegexp)) {
			this.endTimeField.setError(getString(R.string.ErrorInvalidValue));
			valid = false;
		}

		String priority = this.priorityField.getText().toString();
		try {
			Integer.parseInt(priority);
		} catch (Exception ex) {
			this.priorityField.setError(getString(R.string.ErrorInvalidValue));
			valid = false;
		}

		return valid;
	}

	public void refresh() {
		getHandler().post(new Runnable() {
			public void run() {
				initializeSelectLists();
				loadItem();
			}
		});
	}

}
